package com.yanqu.xiuxian.gameserver.tripletown.logic;

import com.yanqu.xiuxian.gameserver.tripletown.config.IConfig;
import com.yanqu.xiuxian.gameserver.tripletown.config.IOrderConfig;
import com.yanqu.xiuxian.gameserver.tripletown.entity.*;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class BombLogic {

    /**
     * 添加炸弹
     */
    public static void addBomb(int fromX, int fromY, int toX, int toY, int round,
                               Map<Integer, Map<Integer, Block>> eliminateMap,
                               Map<Integer, Map<Integer, Block>> dropMap,
                               int[][] copyBlockList, EliminateRoundResult roundResult) {

        List<Block> newBombList = new ArrayList<>();

        Map<Integer, List<List<Block>>> mapListList = BlockLogic.groupSortSameColor(eliminateMap);

        // 【分组生成炸弹】
        for (List<List<Block>> listList : mapListList.values()) {
            for (int i = 0; i < 100 && !listList.isEmpty(); i++) { // 假装是 while
                List<Block> list = listList.remove(listList.size() - 1); // 每次拿最后一组
                if (list.size() < 4) {
                    continue;
                }

                // 转map
                Map<Integer, Map<Integer, Block>> tmpMapMap = new ConcurrentHashMap<>();
                for (int j = 0; j < copyBlockList.length; j++) {
                    tmpMapMap.put(j, new ConcurrentHashMap<>());
                }
                for (Block block : list) {
                    tmpMapMap.get(block.getY()).put(block.getX(), block);
                }

                // 多行5个
                newBombList.addAll(createX(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap, 5, true, 10));
                newBombList.addAll(createY(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap, 5, true, 10));

                // 多行4个
                newBombList.addAll(createX(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap, 4, true, 9));
                newBombList.addAll(createY(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap, 4, true, 9));

                int size = newBombList.size();

                // 单行5个
                newBombList.addAll(createX(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap, 5, false, 10));
                newBombList.addAll(createY(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap, 5, false, 10));
                if (size != newBombList.size()) {
                    listList.add(list); // 剩下的下一轮
                    continue;
                }

                // T型
                newBombList.addAll(createT(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap));
                if (size != newBombList.size()) {
                    listList.add(list); // 剩下的下一轮
                    continue;
                }

                // 单行4个
                newBombList.addAll(createX(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap, 4, false, 9));
                newBombList.addAll(createY(fromX, fromY, toX, toY, round, dropMap, copyBlockList, list, tmpMapMap, 4, false, 9));
                if (size != newBombList.size()) {
                    listList.add(list); // 剩下的下一轮
                }
            }
        }

        // 【添加到每轮结果】
        for (Block block : newBombList) {
            copyBlockList[block.getY()][block.getX()] = block.getC();
            roundResult.addCreateBombBlockList(block);
        }
    }

    public static void addBomb(int fromX, int fromY, int round,
                               Map<Integer, Map<Integer, Block>> eliminateMap,
                               Map<Integer, Map<Integer, Block>> dropMap,
                               int[][] copyBlockList, EliminateRoundResult roundResult) {

        List<Block> newBombList = new ArrayList<>();

        Map<Integer, List<List<Block>>> mapListList = BlockLogic.groupSortSameColor(eliminateMap);

        // 【分组生成炸弹】
        for (List<List<Block>> listList : mapListList.values()) {
            for (int i = 0; i < 100 && !listList.isEmpty(); i++) { // 假装是 while
                List<Block> list = listList.remove(listList.size() - 1); // 每次拿最后一组
                if (list.size() < 4) {
                    continue;
                }

                // 转map
                Map<Integer, Map<Integer, Block>> tmpMapMap = new ConcurrentHashMap<>();
                for (int j = 0; j < copyBlockList.length; j++) {
                    tmpMapMap.put(j, new ConcurrentHashMap<>());
                }
                for (Block block : list) {
                    tmpMapMap.get(block.getY()).put(block.getX(), block);
                }

                // 多行5个
                newBombList.addAll(createX(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap, 5, true, 10));
                newBombList.addAll(createY(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap, 5, true, 10));

                // 多行4个
                newBombList.addAll(createX(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap, 4, true, 9));
                newBombList.addAll(createY(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap, 4, true, 9));

                int size = newBombList.size();

                // 单行5个
                newBombList.addAll(createX(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap, 5, false, 10));
                newBombList.addAll(createY(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap, 5, false, 10));
                if (size != newBombList.size()) {
                    listList.add(list); // 剩下的下一轮
                    continue;
                }

                // T型
                newBombList.addAll(createT(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap));
                if (size != newBombList.size()) {
                    listList.add(list); // 剩下的下一轮
                    continue;
                }

                // 单行4个
                newBombList.addAll(createX(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap, 4, false, 9));
                newBombList.addAll(createY(fromX, fromY, round, dropMap, copyBlockList, list, tmpMapMap, 4, false, 9));
                if (size != newBombList.size()) {
                    listList.add(list); // 剩下的下一轮
                }
            }
        }

        // 【添加到每轮结果】
        for (Block block : newBombList) {
            copyBlockList[block.getY()][block.getX()] = block.getC();
            roundResult.addCreateBombBlockList(block);
        }
    }

    /**
     * 添加订单炸弹
     */
    public static boolean addOrderBomb(Random random, int[][] copyBlockList, Order copyOrder, EliminateRoundResult roundResult, IConfig config) {
        IOrderConfig orderConfig = config.getOrderConfigMap().get(copyOrder.getOrderId());
        if (!orderConfig.getSpecParam().equals("0")) {
            int bombType = Integer.parseInt(orderConfig.getSpecParam());
            if (bombType != 0) {
                // 有炸弹
                int blockCount = copyBlockList.length * copyBlockList[0].length;
                int index = random.nextInt(blockCount);
                for (int b = 0; b < blockCount; b++) {
                    int tmpX = (index + b) % blockCount % copyBlockList[0].length;
                    int tmpY = (index + b) % blockCount / copyBlockList[0].length;
                    // 坐标存在，不为空，不是炸弹
                    if (BlockLogic.existed(copyBlockList, tmpX, tmpY) && copyBlockList[tmpY][tmpX] != 0 && !BlockLogic.isBomb(copyBlockList[tmpY][tmpX])) {
                        // 添加炸弹
                        copyBlockList[tmpY][tmpX] = bombType;
                        // 记录本轮结果
                        roundResult.setOrderBombBlock(new Block(tmpX, tmpY, bombType));
                        return true;
                    }
                }
            }
        }
        return false;
    }


    /**
     * 计算炸弹生成下标
     */
    private static Block createBombBlock(int round, int fromX, int fromY, int toX, int toY, int type,
                                         List<Block> list, Map<Integer, Map<Integer, Block>> dropMap) {
        // 指定炸弹生成位置
        Block coreBlock = null;
        if (round == 1) {
            for (Block block : list) {
                if (block.getX() == toX && block.getY() == toY) {
                    coreBlock = block;
                    break;
                }
                if (block.getX() == fromX && block.getY() == fromY) {
                    coreBlock = block;
                }
            }
        }
        if (coreBlock != null) {
            return new Block(coreBlock.getX(), coreBlock.getY(), type);
        }

        // 下落点判断
        int x = Integer.MAX_VALUE;
        int y = Integer.MAX_VALUE;
        for (Block block : list) {
            if (dropMap.get(block.getY()).containsKey(block.getX())) {
                if (x == Integer.MAX_VALUE || y == Integer.MAX_VALUE) {
                    x = block.getX();
                    y = block.getY();
                } else {
                    if (block.getY() == y) {
                        if (block.getX() < x) {
                            x = block.getX();
                            y = block.getY();
                        }
                    } else {
                        if (block.getY() < y) {
                            x = block.getX();
                            y = block.getY();
                        }
                    }
                }
            }
        }

        // 还没有就返回最小下标
        if (x == Integer.MAX_VALUE || y == Integer.MAX_VALUE) {
            return new Block(list.get(0).getX(), list.get(0).getY(), type);
        } else {
            return new Block(x, y, type);
        }
    }

    private static Block createBombBlock(int round, int fromX, int fromY, int type,
                                         List<Block> list, Map<Integer, Map<Integer, Block>> dropMap) {
        // 指定炸弹生成位置
        Block coreBlock = null;
        if (round == 1) {
            for (Block block : list) {
                if (block.getX() == fromX && block.getY() == fromY) {
                    coreBlock = block;
                }
            }
        }
        if (coreBlock != null) {
            return new Block(coreBlock.getX(), coreBlock.getY(), type);
        }

        // 下落点判断
        int x = Integer.MAX_VALUE;
        int y = Integer.MAX_VALUE;
        for (Block block : list) {
            if (dropMap.get(block.getY()).containsKey(block.getX())) {
                if (x == Integer.MAX_VALUE || y == Integer.MAX_VALUE) {
                    x = block.getX();
                    y = block.getY();
                } else {
                    if (block.getY() == y) {
                        if (block.getX() < x) {
                            x = block.getX();
                            y = block.getY();
                        }
                    } else {
                        if (block.getY() < y) {
                            x = block.getX();
                            y = block.getY();
                        }
                    }
                }
            }
        }

        // 还没有就返回最小下标
        if (x == Integer.MAX_VALUE || y == Integer.MAX_VALUE) {
            return new Block(list.get(0).getX(), list.get(0).getY(), type);
        } else {
            return new Block(x, y, type);
        }
    }

    private static List<Block> createY(int fromX, int fromY, int toX, int toY, int round,
                                       Map<Integer, Map<Integer, Block>> dropMap,
                                       int[][] copyBlockList, List<Block> list,
                                       Map<Integer, Map<Integer, Block>> tmpMapMap,
                                       int continueCount, boolean multi, int bombType) {
        List<List<Block>> groupLineList = new ArrayList<>();
        Map<Integer, Map<Integer, Block>> hadCheckMap = new ConcurrentHashMap<>();
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            hadCheckMap.put(tmpY, new ConcurrentHashMap<>());
        }
        for (Block block : list) {
            if (hadCheckMap.get(block.getY()).containsKey(block.getX())) {
                continue;
            }
            hadCheckMap.get(block.getY()).put(block.getX(), block);
            List<Block> tmpList = new ArrayList<>();
            tmpList.add(block);
            for (int y = block.getY() + 1; y < copyBlockList.length && y < block.getY() + continueCount; y++) {
                Block tmpBlock = tmpMapMap.get(y).get(block.getX());
                if (tmpBlock != null) {
                    tmpList.add(tmpBlock);
                    hadCheckMap.get(tmpBlock.getY()).put(tmpBlock.getX(), tmpBlock);
                } else break;
            }
            if (tmpList.size() == continueCount) groupLineList.add(tmpList);
        }
        List<Block> bombList = new ArrayList<>();
        if (multi && groupLineList.size() > 1 || !multi && groupLineList.size() == 1) {
            for (List<Block> useList : groupLineList) {
                // 计算生成位置
                bombList.add(createBombBlock(round, fromX, fromY, toX, toY, bombType, useList, dropMap));
                for (Block block : useList) {
                    // map移除方块
                    tmpMapMap.get(block.getY()).remove(block.getX());
                    // list移除方块
                    list.remove(block);
                }
            }
        }
        return bombList;
    }

    private static List<Block> createY(int fromX, int fromY, int round,
                                       Map<Integer, Map<Integer, Block>> dropMap,
                                       int[][] copyBlockList, List<Block> list,
                                       Map<Integer, Map<Integer, Block>> tmpMapMap,
                                       int continueCount, boolean multi, int bombType) {
        List<List<Block>> groupLineList = new ArrayList<>();
        Map<Integer, Map<Integer, Block>> hadCheckMap = new ConcurrentHashMap<>();
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            hadCheckMap.put(tmpY, new ConcurrentHashMap<>());
        }
        for (Block block : list) {
            if (hadCheckMap.get(block.getY()).containsKey(block.getX())) {
                continue;
            }
            hadCheckMap.get(block.getY()).put(block.getX(), block);
            List<Block> tmpList = new ArrayList<>();
            tmpList.add(block);
            for (int y = block.getY() + 1; y < copyBlockList.length && y < block.getY() + continueCount; y++) {
                Block tmpBlock = tmpMapMap.get(y).get(block.getX());
                if (tmpBlock != null) {
                    tmpList.add(tmpBlock);
                    hadCheckMap.get(tmpBlock.getY()).put(tmpBlock.getX(), tmpBlock);
                } else break;
            }
            if (tmpList.size() == continueCount) groupLineList.add(tmpList);
        }
        List<Block> bombList = new ArrayList<>();
        if (multi && groupLineList.size() > 1 || !multi && groupLineList.size() == 1) {
            for (List<Block> useList : groupLineList) {
                // 计算生成位置
                bombList.add(createBombBlock(round, fromX, fromY, bombType, useList, dropMap));
                for (Block block : useList) {
                    // map移除方块
                    tmpMapMap.get(block.getY()).remove(block.getX());
                    // list移除方块
                    list.remove(block);
                }
            }
        }
        return bombList;
    }

    private static List<Block> createX(int fromX, int fromY, int toX, int toY, int round,
                                       Map<Integer, Map<Integer, Block>> dropMap,
                                       int[][] copyBlockList, List<Block> list,
                                       Map<Integer, Map<Integer, Block>> tmpMapMap,
                                       int continueCount, boolean multi, int bombType) {
        List<List<Block>> groupLineList = new ArrayList<>();
        Map<Integer, Map<Integer, Block>> hadCheckMap = new ConcurrentHashMap<>();
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            hadCheckMap.put(tmpY, new ConcurrentHashMap<>());
        }
        for (Block block : list) {
            if (hadCheckMap.get(block.getY()).containsKey(block.getX())) {
                continue;
            }
            hadCheckMap.get(block.getY()).put(block.getX(), block);
            List<Block> tmpList = new ArrayList<>();
            tmpList.add(block);
            for (int x = block.getX() + 1; x > 0 && x < block.getX() + continueCount; x++) {
                Block tmpBlock = tmpMapMap.get(block.getY()).get(x);
                if (tmpBlock != null) {
                    tmpList.add(tmpBlock);
                    hadCheckMap.get(tmpBlock.getY()).put(tmpBlock.getX(), tmpBlock);
                } else {
                    break;
                }
            }
            if (tmpList.size() == continueCount) {
                groupLineList.add(tmpList);
            }
        }
        List<Block> bombList = new ArrayList<>();
        if (multi && groupLineList.size() > 1 || !multi && groupLineList.size() == 1) {
            for (List<Block> useList : groupLineList) {
                // 计算生成位置
                bombList.add(createBombBlock(round, fromX, fromY, toX, toY, bombType, useList, dropMap));
                for (Block block : useList) {
                    // map移除方块
                    tmpMapMap.get(block.getY()).remove(block.getX());
                    // list移除方块
                    list.remove(block);
                }
            }
        }
        return bombList;
    }

    private static List<Block> createX(int fromX, int fromY, int round,
                                       Map<Integer, Map<Integer, Block>> dropMap,
                                       int[][] copyBlockList, List<Block> list,
                                       Map<Integer, Map<Integer, Block>> tmpMapMap,
                                       int continueCount, boolean multi, int bombType) {
        List<List<Block>> groupLineList = new ArrayList<>();
        Map<Integer, Map<Integer, Block>> hadCheckMap = new ConcurrentHashMap<>();
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            hadCheckMap.put(tmpY, new ConcurrentHashMap<>());
        }
        for (Block block : list) {
            if (hadCheckMap.get(block.getY()).containsKey(block.getX())) {
                continue;
            }
            hadCheckMap.get(block.getY()).put(block.getX(), block);
            List<Block> tmpList = new ArrayList<>();
            tmpList.add(block);
            for (int x = block.getX() + 1; x > 0 && x < block.getX() + continueCount; x++) {
                Block tmpBlock = tmpMapMap.get(block.getY()).get(x);
                if (tmpBlock != null) {
                    tmpList.add(tmpBlock);
                    hadCheckMap.get(tmpBlock.getY()).put(tmpBlock.getX(), tmpBlock);
                } else {
                    break;
                }
            }
            if (tmpList.size() == continueCount) {
                groupLineList.add(tmpList);
            }
        }
        List<Block> bombList = new ArrayList<>();
        if (multi && groupLineList.size() > 1 || !multi && groupLineList.size() == 1) {
            for (List<Block> useList : groupLineList) {
                // 计算生成位置
                bombList.add(createBombBlock(round, fromX, fromY, bombType, useList, dropMap));
                for (Block block : useList) {
                    // map移除方块
                    tmpMapMap.get(block.getY()).remove(block.getX());
                    // list移除方块
                    list.remove(block);
                }
            }
        }
        return bombList;
    }

    private static List<Block> createT(int fromX, int fromY, int toX, int toY, int round,
                                       Map<Integer, Map<Integer, Block>> dropMap,
                                       int[][] copyBlockList, List<Block> list,
                                       Map<Integer, Map<Integer, Block>> tmpMapMap) {
        List<List<Block>> groupLineList = new ArrayList<>();
        Map<Integer, Map<Integer, Block>> hadCheckMap = new ConcurrentHashMap<>();
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            hadCheckMap.put(tmpY, new ConcurrentHashMap<>());
        }
        for (Block block : list) {
            if (hadCheckMap.get(block.getY()).containsKey(block.getX())) continue;
            List<Block> tmpList = new ArrayList<>();
            tmpList.add(block);

            for (int y = block.getY() - 1; y >= 0 && tmpList.size() < 3; y--) {
                Block tmpBlock = tmpMapMap.get(y).get(block.getX());
                if (tmpBlock != null && !hadCheckMap.get(tmpBlock.getY()).containsKey(tmpBlock.getX())) {
                    tmpList.add(tmpBlock);
                } else {
                    break;
                }
            }
            for (int y = block.getY() + 1; y < copyBlockList.length && tmpList.size() < 3; y++) {
                Block tmpBlock = tmpMapMap.get(y).get(block.getX());
                if (tmpBlock != null && !hadCheckMap.get(tmpBlock.getY()).containsKey(tmpBlock.getX())) {
                    tmpList.add(tmpBlock);
                } else {
                    break;
                }
            }
            if (tmpList.size() < 3) {
                continue; // 无法生成
            }
            for (int x = block.getX() - 1; x >= 0 && tmpList.size() < 5; x--) {
                Block tmpBlock = tmpMapMap.get(block.getY()).get(x);
                if (tmpBlock != null && !hadCheckMap.get(tmpBlock.getY()).containsKey(tmpBlock.getX())) {
                    tmpList.add(tmpBlock);
                } else {
                    break;
                }
            }
            for (int x = block.getX() + 1; x < copyBlockList[0].length && tmpList.size() < 5; x++) {
                Block tmpBlock = tmpMapMap.get(block.getY()).get(x);
                if (tmpBlock != null && !hadCheckMap.get(tmpBlock.getY()).containsKey(tmpBlock.getX())) {
                    tmpList.add(tmpBlock);
                } else {
                    break;
                }
            }
            if (tmpList.size() == 5) {
                groupLineList.add(tmpList);
                for (Block block1 : tmpList) {
                    hadCheckMap.get(block1.getY()).put(block1.getX(), block1);
                }
            }
        }
        List<Block> bombList = new ArrayList<>();
        if (!groupLineList.isEmpty()) {
            for (List<Block> useList : groupLineList) {
                // 计算生成位置
                bombList.add(createBombBlock(round, fromX, fromY, toX, toY, 10, useList, dropMap));
                for (Block block : useList) {
                    // map移除方块
                    tmpMapMap.get(block.getY()).remove(block.getX());
                    // list移除方块
                    list.remove(block);
                }
            }
        }
        return bombList;
    }

    private static List<Block> createT(int fromX, int fromY, int round,
                                       Map<Integer, Map<Integer, Block>> dropMap,
                                       int[][] copyBlockList, List<Block> list,
                                       Map<Integer, Map<Integer, Block>> tmpMapMap) {
        List<List<Block>> groupLineList = new ArrayList<>();
        Map<Integer, Map<Integer, Block>> hadCheckMap = new ConcurrentHashMap<>();
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            hadCheckMap.put(tmpY, new ConcurrentHashMap<>());
        }
        for (Block block : list) {
            if (hadCheckMap.get(block.getY()).containsKey(block.getX())) continue;
            List<Block> tmpList = new ArrayList<>();
            tmpList.add(block);

            for (int y = block.getY() - 1; y >= 0 && tmpList.size() < 3; y--) {
                Block tmpBlock = tmpMapMap.get(y).get(block.getX());
                if (tmpBlock != null && !hadCheckMap.get(tmpBlock.getY()).containsKey(tmpBlock.getX())) {
                    tmpList.add(tmpBlock);
                } else {
                    break;
                }
            }
            for (int y = block.getY() + 1; y < copyBlockList.length && tmpList.size() < 3; y++) {
                Block tmpBlock = tmpMapMap.get(y).get(block.getX());
                if (tmpBlock != null && !hadCheckMap.get(tmpBlock.getY()).containsKey(tmpBlock.getX())) {
                    tmpList.add(tmpBlock);
                } else {
                    break;
                }
            }
            if (tmpList.size() < 3) {
                continue; // 无法生成
            }
            for (int x = block.getX() - 1; x >= 0 && tmpList.size() < 5; x--) {
                Block tmpBlock = tmpMapMap.get(block.getY()).get(x);
                if (tmpBlock != null && !hadCheckMap.get(tmpBlock.getY()).containsKey(tmpBlock.getX())) {
                    tmpList.add(tmpBlock);
                } else {
                    break;
                }
            }
            for (int x = block.getX() + 1; x < copyBlockList[0].length && tmpList.size() < 5; x++) {
                Block tmpBlock = tmpMapMap.get(block.getY()).get(x);
                if (tmpBlock != null && !hadCheckMap.get(tmpBlock.getY()).containsKey(tmpBlock.getX())) {
                    tmpList.add(tmpBlock);
                } else {
                    break;
                }
            }
            if (tmpList.size() == 5) {
                groupLineList.add(tmpList);
                for (Block block1 : tmpList) {
                    hadCheckMap.get(block1.getY()).put(block1.getX(), block1);
                }
            }
        }
        List<Block> bombList = new ArrayList<>();
        if (!groupLineList.isEmpty()) {
            for (List<Block> useList : groupLineList) {
                // 计算生成位置
                bombList.add(createBombBlock(round, fromX, fromY, 10, useList, dropMap));
                for (Block block : useList) {
                    // map移除方块
                    tmpMapMap.get(block.getY()).remove(block.getX());
                    // list移除方块
                    list.remove(block);
                }
            }
        }
        return bombList;
    }

    /**
     * 处理炸弹
     */
    public static void handleBomb(int[][] copyBlockList, Map<Integer, Map<Integer, Block>> eliminateMap, int fromX, int fromY,
                                        int toX, int toY, EliminateStageResult eliminateStageResult, List<Block> waitBombBlockList) {
        int type = 0; // 炸弹类型
        int x = -1; // 爆炸中心
        int y = -1; // 爆炸中心

        boolean fromBomb = BlockLogic.isBomb(copyBlockList[fromY][fromX]);
        boolean toBomb = BlockLogic.isBomb(copyBlockList[toY][toX]);
        // 判断首次炸弹爆炸
        if (fromBomb && toBomb) {
            if (copyBlockList[fromY][fromX] == 9 && copyBlockList[toY][toX] == 9) { // 九宫格炸弹 * 2
                x = toX;
                y = toY;
                type = 6;
            } else if (copyBlockList[fromY][fromX] == 9 && copyBlockList[toY][toX] == 10 ||
                    copyBlockList[fromY][fromX] == 10 && copyBlockList[toY][toX] == 9) { // 九宫格炸弹 && 十字炸弹
                y = toY;
                x = toX;
                type = fromY == toY ? 3 : 4;
            } else if (copyBlockList[fromY][fromX] == 10 && copyBlockList[toY][toX] == 10) { // 十字炸弹 * 2
                x = toX;
                y = toY;
                type = 5;
            }
        } else {
            // 普通炸弹
            if (fromBomb) {
                x = fromX;
                y = fromY;
                type = copyBlockList[fromY][fromX] == 9 ? 2 : 1;
            } else if (toBomb) {
                x = toX;
                y = toY;
                type = copyBlockList[toY][toX] == 9 ? 2 : 1;
            }
        }

        // 爆炸
        if (type != 0) {
            List<Block> blockList = calBombEliminateList(copyBlockList, x, y, type);
            for (Block block : blockList) {
                // 记录消除的格子
                if (!eliminateMap.get(block.getY()).containsKey(block.getX())) {
                    eliminateMap.get(block.getY()).put(block.getX(), block);
                    // 记录等会儿要爆炸的格子（要排除掉自身）
                    if (BlockLogic.isBomb(block.getC()) && !(block.getY() == fromY && block.getX() == fromX || block.getY() == toY && block.getX() == toX)) {
                        waitBombBlockList.add(block);
                    }
                    // 记录阶段数据
                    eliminateStageResult.addBlock(block);
                }
            }
            eliminateStageResult.addBomb(new Bomb(x, y, type));
        }
    }

    public static void handleBomb(int[][] copyBlockList, Map<Integer, Map<Integer, Block>> eliminateMap, int fromX, int fromY,
                                  EliminateStageResult eliminateStageResult, List<Block> waitBombBlockList) {
        int type = 0; // 炸弹类型

        boolean fromBomb = BlockLogic.isBomb(copyBlockList[fromY][fromX]);
        if (fromBomb) {
            type = copyBlockList[fromY][fromX] == 9 ? 2 : 1;
        }

        // 爆炸
        if (type != 0) {
            List<Block> blockList = calBombEliminateList(copyBlockList, fromX, fromY, type);
            for (Block block : blockList) {
                // 记录消除的格子
                if (!eliminateMap.get(block.getY()).containsKey(block.getX())) {
                    eliminateMap.get(block.getY()).put(block.getX(), block);
                    // 记录等会儿要爆炸的格子（要排除掉自身）
                    if (BlockLogic.isBomb(block.getC()) && !(block.getY() == fromY && block.getX() == fromX)) {
                        waitBombBlockList.add(block);
                    }
                    // 记录阶段数据
                    eliminateStageResult.addBlock(block);
                }
            }
            eliminateStageResult.addBomb(new Bomb(fromX, fromY, type));
        }
    }

    /**
     * 计算爆炸消除的点（这里没过滤，可能重复）
     *
     * @param type 爆炸范围类型：0无，1十字，2九宫格，3横三竖一，4横一竖三，5横三竖三，6二十五宫格
     */
    public static List<Block> calBombEliminateList(int[][] blockList, int stopX, int stopY, int type) {
        List<Block> list = new ArrayList<>();
        switch (type) {
            case 1:
                for (int x = 0; x < blockList[stopY].length; x++) {
                    list.add(new Block(x, stopY, blockList[stopY][x]));
                }
                for (int y = 0; y < blockList.length; y++) {
                    list.add(new Block(stopX, y, blockList[y][stopX]));
                }
                break;
            case 2:
                for (int y = stopY - 1; y <= stopY + 1; y++) {
                    for (int x = stopX - 1; x <= stopX + 1; x++) {
                        if (BlockLogic.existed(blockList, x, y)) {
                            list.add(new Block(x, y, blockList[y][x]));
                        }
                    }
                }
                break;
            case 3:
                for (int y = stopY - 1; y <= stopY + 1; y++) {
                    for (int x = 0; x < blockList[0].length; x++) {
                        if (BlockLogic.existed(blockList, x, y)) {
                            list.add(new Block(x, y, blockList[y][x]));
                        }
                    }
                }
                for (int y = 0; y < blockList.length; y++) {
                    list.add(new Block(stopX, y, blockList[y][stopX]));
                }
                break;
            case 4:
                for (int x = 0; x < blockList[stopY].length; x++) {
                    list.add(new Block(x, stopY, blockList[stopY][x]));
                }
                for (int y = 0; y < blockList.length; y++) {
                    for (int x = stopX - 1; x <= stopX + 1; x++) {
                        if (BlockLogic.existed(blockList, x, y)) {
                            list.add(new Block(x, y, blockList[y][x]));
                        }
                    }
                }
                break;
            case 5:
                for (int y = stopY - 1; y <= stopY + 1; y++) {
                    for (int x = 0; x < blockList[0].length; x++) {
                        if (BlockLogic.existed(blockList, x, y)) {
                            list.add(new Block(x, y, blockList[y][x]));
                        }
                    }
                }
                for (int y = 0; y < blockList.length; y++) {
                    for (int x = stopX - 1; x <= stopX + 1; x++) {
                        if (BlockLogic.existed(blockList, x, y)) {
                            list.add(new Block(x, y, blockList[y][x]));
                        }
                    }
                }
                break;
            case 6:
                for (int y = stopY - 2; y <= stopY + 2; y++) {
                    for (int x = stopX - 2; x <= stopX + 2; x++) {
                        if (BlockLogic.existed(blockList, x, y)) {
                            list.add(new Block(x, y, blockList[y][x]));
                        }
                    }
                }
                break;
        }
        return list;
    }

    public static List<Block> calBombEliminateList(int[][] blockList, Block block) {
        int type = getBombType(blockList,block);
        return calBombEliminateList(blockList, block.getX(), block.getY(), type);
    }

    public static int getBombType(int[][] blockList, Block block) {
        return getBombType(blockList, block.getX(), block.getY());
    }

    public static int getBombType(int[][] blockList, int x, int y) {
        int color = blockList[y][x];
        if (color == 9) {
            return 2;
        }
        if (color == 10) {
            return 1;
        }
        return 0;
    }

    /**
     * 处理炸弹爆炸
     *
     * @return 下阶段爆炸的炸弹
     */
    public static List<Block> handleBombExploded(int[][] copyBlockList, Map<Integer, Map<Integer, Block>> eliminateMap,
                                                  EliminateStageResult eliminateStageResult, List<Block> waitBombBlockList) {
        List<Block> nextWaitBombBlockList = new ArrayList<>();
        for (Block bomb : waitBombBlockList) {
            eliminateStageResult.addBomb(new Bomb(bomb.getX(), bomb.getY(), bomb.getC() == 9 ? 2 : 1));
            List<Block> blockList = calBombEliminateList(copyBlockList, bomb.getX(), bomb.getY(), bomb.getC() == 9 ? 2 : 1);
            for (Block block : blockList) {
                if (!eliminateMap.get(block.getY()).containsKey(block.getX())) {
                    eliminateMap.get(block.getY()).put(block.getX(), block);
                    eliminateStageResult.addBlock(block);
                    if (BlockLogic.isBomb(block)) {
                        nextWaitBombBlockList.add(block);
                    }
                }
            }
        }
        return nextWaitBombBlockList;
    }

}
